/*
 * Copyright 2004 - 2006 Arnold Krille <arnold@arnoldarts.de>
 * Copyright 2007 Stéphane Brunner <stephane.brunner@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY, without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 */

#include "mainwindow.h"
#include "mainwindow.moc"

#include "page_capture.h"
//#include "raw1394util.h"
#include <libraw1394/raw1394.h>
#include <libavc1394/rom1394.h>

//#include <iostream>
//using namespace std;
#include <sys/time.h>

#include <QDebug>
#include <QVBoxLayout>
#include <QScrollArea>
#include "video.h"

#define MOTDCT_SPEC_ID    0x00005068


namespace VideoMix
{

MainWindow::MainWindow(QWidget* p) : QMainWindow(p)
{
cerr<<999<<endl;
    qDebug() << "MainWindow::MainWindow()";

    QWidget *w = new QWidget();
    setCentralWidget(w);

//QVBoxLayout *l = NULL;
//l->addWidget(w);
    QVBoxLayout *layout = new QVBoxLayout(w);

    int port = -1;
    int channel = -1;
    uint64_t guid = 0;
    int node = discoverAVC(&port, &guid, 0);

    if (node == -1) {
        qDebug() << "no camera exists";
    }
    else {
        raw1394handle_t handle = raw1394_new_handle_on_port( port );
        if ( handle )
        {
            int bandwidth;
            int outputPort;
            int inputPort;

            channel = iec61883_cmp_connect( handle, node, &outputPort, raw1394_get_local_id( handle ), &inputPort, &bandwidth );
            if ( channel < 0 ) {
                channel = 63;
            }

            iec61883_cmp_disconnect( handle, node, outputPort, raw1394_get_local_id (handle), inputPort, channel, bandwidth );
            raw1394_destroy_handle( handle );
        }
//        iec61883Connection *connection = new iec61883Connection(port, node);
//        if (!connection)
        else {
            qDebug() << "failed to establish isochronous connection";
        }
//        channel = connection->GetChannel();
        qDebug("Found AV/C (channel: %i, port: %i, node: %i) ", channel, port, node);
    }

    #define PREVIEW_SCALE 1
    //QWidget *vwidget1
    video = new GLVideo(720/PREVIEW_SCALE, 576/PREVIEW_SCALE);
    #define SCALE 2
    QWidget *vwidget = new GLVideo(720/SCALE, 576/SCALE);
//    vwidget->setFixedSize(720, 576); // 40ms
//    vwidget->setFixedSize(720*2/3, 576*2/3); // 15ms
//    vwidget->setFixedSize(720/2, 576/2); // 9ms
//    vwidget->setFixedSize(720/4, 576/4); // 3ms

    layout->addWidget(vwidget);
    layout->addWidget(video);
//    layout->addWidget(vwidget);
    if (node != -1) {
        PageCapture *pageCapture = new PageCapture();
        pageCapture->setScreen1(video);
        pageCapture->start(QThread::TimeCriticalPriority);
qDebug()<<666;
        pageCapture->addInput(vwidget, channel, port);
qDebug()<<777;
    }

/*    avpicture_alloc(&black, PIX_FMT_RGB32, 720, 576);
    avpicture_alloc(&white, PIX_FMT_RGB32, 720, 576);

    for (int i = 0 ; i < 720 * 576 ; i++) {
        black.data[0][i*4 + 3] = (unsigned char)255;
    }

    white.data[0][1] = (unsigned char)255;
    white.data[0][5] = (unsigned char)255;
    white.data[0][720*4 + 1] = (unsigned char)255;

    white.data[0][719*4+1] = (unsigned char)255;
    white.data[0][719*4+720*4+1] = (unsigned char)255;
    white.data[0][719*4-3] = (unsigned char)255;

    white.data[0][720*414*4+725*4+1] = (unsigned char)255;

    white.data[0][720*576*2+1] = (unsigned char)255;
    white.data[0][720*576*2+720*2+1] = (unsigned char)255;
    white.data[0][720*576*2+720*4-2-4] = (unsigned char)255;
    white.data[0][720*576*2+720*4-1-4] = (unsigned char)255;
    white.data[0][720*576*2+720*4*2-3-4] = (unsigned char)255;
    white.data[0][720*576*2+720*4*2-1-4] = (unsigned char)255;

    white.data[0][720*575*4+1] = (unsigned char)255;
    white.data[0][720*575*4+5] = (unsigned char)255;
    white.data[0][720*575*4-720*4+1] = (unsigned char)255;

    white.data[0][720*576*4-3] = (unsigned char)255;
    white.data[0][720*576*4-720*4-3] = (unsigned char)255;
    white.data[0][720*576*4-7] = (unsigned char)255;


    white.data[0][720*576] = (unsigned char)255;
    white.data[0][720*576+1] = (unsigned char)255;
    white.data[0][720*576+2] = (unsigned char)255;
    
    white.data[0][720*576-720*4+576*2+1] = (unsigned char)255;
    white.data[0][720*576-720*8+576*2+1] = (unsigned char)255;
    white.data[0][720*576-720*12+576*2+1] = (unsigned char)255;
    
    white.data[0][720*576+576*2] = (unsigned char)255;
    white.data[0][720*576+576*2+1] = (unsigned char)255;
    white.data[0][720*576+576*2+2] = (unsigned char)255;
    
    white.data[0][720*576+576*2+4] = (unsigned char)255;
    white.data[0][720*576+576*2+8] = (unsigned char)255;
    white.data[0][720*576+576*2+12+1] = (unsigned char)255;
    white.data[0][720*576+576*2+16+1] = (unsigned char)255;
    white.data[0][720*576+576*2+20+2] = (unsigned char)255;
    white.data[0][720*576+576*2+24+2] = (unsigned char)255;
    
    for (int i = 0 ; i < 720 * 576 ; i++) {
        white.data[0][i*4 + 3] = (unsigned char)255;
    }
    for (int i = 0 ; i < 720 * 576 * 4 ; i++) {
        white.data[0][i] = (unsigned char)255;
    }

    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    timer->start(130);*/

    show();
qDebug()<<222;
    qDebug() << "MainWindow::MainWindow() finished...";
}

MainWindow::~MainWindow()
{
    qDebug() << "MainWindow::~MainWindow()";
}


int MainWindow::discoverAVC( int* port, octlet_t* guid, int fromDevice )
{
    rom1394_directory rom_dir;
    raw1394handle_t handle;
    int device = -1;
    int i = fromDevice;
    int j = 0;
//    int m = raw1394_get_num_ports();
    int m;
    struct raw1394_portinfo pinf[ 16 ];

    /* get a raw1394 handle */
    if ( !( handle = raw1394_new_handle() ) )
    {
        qDebug("raw1394 - failed to get handle.");
        exit( EXIT_FAILURE );
    }

    if ( ( m = raw1394_get_port_info( handle, pinf, 16 ) ) < 0 )
    {
        qDebug("raw1394 - failed to get port info.");
        raw1394_destroy_handle( handle );
        exit( EXIT_FAILURE );
    }
    raw1394_destroy_handle( handle );
    
    
    if ( *port >= 0 )
    {
        /* search from explicit port */
        j = *port;
//        m = *port + 1;
    }

    for ( ; j < m && device == -1; j++ )
    {
//        handle = raw1394_open( j );
        int n_ports;
        struct raw1394_portinfo pinf[ 16 ];
        raw1394handle_t handle;

        /* get a raw1394 handle */
    #ifdef RAW1394_V_0_8

        handle = raw1394_get_handle();
    #else

        handle = raw1394_new_handle();
    #endif

        if ( !handle )
        {
            qDebug( "raw1394 - failed to get handle." );
            exit( EXIT_FAILURE );
        }

        if ( ( n_ports = raw1394_get_port_info( handle, pinf, 16 ) ) < 0 )
        {
            qDebug( "raw1394 - failed to get port info." );
            raw1394_destroy_handle( handle );
            exit( EXIT_FAILURE );
        }

        /* tell raw1394 which host adapter to use */
        if ( raw1394_set_port( handle, j ) < 0 )
        {
            qDebug( "raw1394 - failed to set set port." );
            exit( EXIT_FAILURE );
        }
        
        for ( ; i < raw1394_get_nodecount( handle ); ++i )
        {
            if ( *guid > 1 )
            {
                /* select explicitly by GUID */
                if ( *guid == rom1394_get_guid( handle, i ) )
                {
                    device = i;
                    *port = j;
                    break;
                }
            }
            else
            {
                /* select first AV/C Tape Reccorder Player node */
                if ( rom1394_get_directory( handle, i, &rom_dir ) < 0 )
                {
                    fprintf( stderr, "error reading config rom directory for node %d\n", i );
                    continue;
                }
                if ( ( ( rom1394_get_node_type( &rom_dir ) == ROM1394_NODE_TYPE_AVC ) &&
                         avc1394_check_subunit_type( handle, i, AVC1394_SUBUNIT_TYPE_VCR ) ) ||
                       ( rom_dir.unit_spec_id == MOTDCT_SPEC_ID ) )
                {
                    octlet_t my_guid, *pguid = ( *guid == 1 )? guid : &my_guid;
                    *pguid = rom1394_get_guid( handle, i );
                    fprintf( stderr, "Found AV/C device with GUID 0x%08x%08x\n",
                        (quadlet_t) (*pguid>>32), (quadlet_t) (*pguid & 0xffffffff));
                    device = i;
                    *port = j;
                    break;
                }
            }
        }
        i = 0;
        raw1394_destroy_handle( handle );
    }

    return device;
}
/*
void MainWindow::update() {
//    video->setFrame(white);
    video->setFrame(isWhite ? &black : &white);
    isWhite = !isWhite;
}*/

}
; //VideoMix
